/*
 * Copyright 2015-2018 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.willowtreeapps.opentest4k

import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertFalse
import kotlin.test.assertTrue

/**
 * Unit tests for [MultipleFailuresError].
 *
 * @author Marc Philipp
 * @author Sam Brannen
 * @since 1.0
 */
class MultipleFailuresErrorTests {

    @Test
    fun mfeWithNoFailuresWithNullHeading() {
        assertExceptionWithNoFailures(null, DEFAULT_HEADING)
    }

    @Test
    fun mfeWithNoFailuresWithEmptyHeading() {
        assertExceptionWithNoFailures("    ", DEFAULT_HEADING)
    }

    @Test
    fun mfeWithNoFailuresWithCustomHeading() {
        assertExceptionWithNoFailures(HEADING, HEADING)
    }

    @Test
    fun mfeWithSingleFailureWithNullHeading() {
        assertExceptionWithSingleFailure(null, DEFAULT_HEADING)
    }

    @Test
    fun mfeWithSingleFailureWithEmptyHeading() {
        assertExceptionWithSingleFailure("   ", DEFAULT_HEADING)
    }

    @Test
    fun mfeWithSingleFailureWithCustomHeading() {
        assertExceptionWithSingleFailure(HEADING, HEADING)
    }

    @Test
    fun mfeWithFailuresWithNullHeading() {
        assertExceptionWithFailures(null, DEFAULT_HEADING)
    }

    @Test
    fun mfeWithFailuresWithEmptyHeading() {
        assertExceptionWithFailures("   ", DEFAULT_HEADING)
    }

    @Test
    fun mfeWithFailuresWithCustomHeading() {
        assertExceptionWithFailures(HEADING, HEADING)
    }

    @Test
    fun mfeWithNullMessageFailures() {
        val failures = listOf(
            AssertionError(),
            AssertionFailedError()
        )

        val mfe =
            MultipleFailuresError(HEADING, failures)

        assertEquals(
            """$HEADING (2 failures)
	${AssertionErrorName}: <no message>
	${AssertionFailedErrorName}: <no message>""",
            mfe.message
        )
    }

    private fun assertExceptionWithNoFailures(inputHeading: String?, outputHeading: String) {
        val mfe = MultipleFailuresError(inputHeading, emptyList())

        assertTrue(mfe.failures.isEmpty())
        assertFalse(mfe.hasFailures())
        assertEquals(outputHeading, mfe.message)
    }

    private fun assertExceptionWithSingleFailure(inputHeading: String?, outputHeading: String) {
        val failures = ArrayList<Throwable>()
        failures.add(AssertionError("failure 1"))

        val mfe = MultipleFailuresError(inputHeading, failures)

        assertEquals(1, mfe.failures.size.toLong())
        assertTrue(mfe.hasFailures())
        assertEquals(
            """$outputHeading (1 failure)
	${AssertionErrorName}: failure 1""",
            mfe.message
        )
    }

    private fun assertExceptionWithFailures(inputHeading: String?, outputHeading: String) {
        val failures = ArrayList<Throwable>()
        failures.add(AssertionError("failure 1"))
        failures.add(AssertionError("failure 2"))

        val mfe = MultipleFailuresError(inputHeading, failures)

        assertEquals(2, mfe.failures.size.toLong())
        assertTrue(mfe.hasFailures())
        assertEquals(
            """$outputHeading (2 failures)
	${AssertionErrorName}: failure 1
	${AssertionErrorName}: failure 2""",
            mfe.message
        )
    }
}

private const val DEFAULT_HEADING = "Multiple Failures"
private const val HEADING = "Custom Heading"
